package wcu;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;

public class WCUController {
	private static String inline;
	private static BufferedReader instream;
	private static DataOutputStream outstream;

	private Database db;
	private UI ui;
	private String stringFromServer;
	int id = 0;
	int vareNummer = 0;
	double tara = 0;
	double netto = 0;
	double brutto = 0;

	public WCUController(UI ui, Database db) throws UnknownHostException,
			InterruptedException {
		this.db = db;
		this.ui = ui;

		// Connection to ScaleSim
		try {
			// Set the port and IP here
			Network.getInstance().connectToServer("localhost", 8000);
		} catch (IOException e) {
			System.out.println("Couldn't find ip or port");
		}

		// OVERBLIK
		// This program sets the user in different phases which has been
		// analyzed by looking at the flow
		// 1. Login
		// 2. Get and select a product
		// 3. Set and confirm Tara
		// 4. Set and confirm Netto
		// 5. Brutto Control
		// 6. Log the change in the log.txt file and add the new value to the
		// store.txt file
		// 7. Restart, go to 1.

		boolean running = true;
		while (running) {
			loginPhase();
			vareNummer = findProductPhase();
			tara = taraPhase();
			netto = nettoPhase();
			bruttoControlPhase(netto, tara);
			logAndStorePhase();
		}
	}

	private int loginPhase() throws UnknownHostException, InterruptedException {
		String operatoerId = "";
		boolean UserLoggedOn = false;
		boolean waitingForId = true;
		while (waitingForId) {
			Network.getInstance().getMettlerScaleCommands()
					.sendRM20("8", "Operator id?", "x3");

			while (!UserLoggedOn) {
				stringFromServer = Network.getInstance().readFromServer();

				// Prints stream in the WCU console
				if (!stringFromServer.isEmpty()) {
					ui.writeToConsole(stringFromServer);
				}

				// Takes the ID, checks if number and
				if (stringFromServer.contains("RM20 A")) {
					operatoerId = stringFromServer.split("\"")[1];

					if (CommonUtil.isNumber(operatoerId)) {
						UserLoggedOn = true;
						return Integer.parseInt(operatoerId);
					} else {
						Network.getInstance().getMettlerScaleCommands()
								.sendRM20("8", "Operator id? Kun Numre", "x3");

					}
				}
			}
		}
		return 0;
	}

	private int findProductPhase() throws UnknownHostException,
			InterruptedException {
		String productInfo = "";
		String productName = "";
		boolean userConfirmed;
		boolean productFound = false;

		Network.getInstance().getMettlerScaleCommands()
				.sendRM20("8", "Vare nr?", "x3");

		while (!productFound) {
			Thread.sleep(100);
			stringFromServer = Network.getInstance().readFromServer();

			if (!stringFromServer.isEmpty()) {
				ui.writeToConsole(stringFromServer);
			}

			if (productInfo.equals("notfound")) {
				Network.getInstance()
						.getMettlerScaleCommands()
						.sendRM20("8", "Eksisterer ikke, indtast andet nummer",
								"x3");
				productInfo = "";
			}

			// Searching for product
			if (stringFromServer.contains("A")) {
				stringFromServer = stringFromServer.split("\"")[1];
				productInfo = db.searchStoreFile(stringFromServer);
			}

			// Product found
			if (!productInfo.equals("notfound") && !productInfo.isEmpty()) {
				// Verificering
				userConfirmed = false;
				System.out.println("PRODUCTINFO: " + productInfo);
				System.out.println(productInfo.split(",")[1]);
				productName = productInfo.split(",")[1].split("=")[1];

				Network.getInstance()
						.getMettlerScaleCommands()
						.sendRM20("8", "Fortsæt med " + productName + "? y/n",
								"x3");

				// Ask user to confirm product
				while (!userConfirmed) {
					Thread.sleep(100);
					stringFromServer = Network.getInstance().readFromServer();

					// Prints stream in WCU
					if (!stringFromServer.isEmpty()) {
						ui.writeToConsole(stringFromServer);
					}

					if (stringFromServer.contains("RM20 A")) {
						// Yes
						if (stringFromServer.split("\"")[1].toLowerCase()
								.equals("y")) {
							productFound = true;
							userConfirmed = true;
							System.out.println(productInfo);
							System.out.println(productInfo);
							int vareNr = Integer.parseInt(productInfo.split(",")[0].split("=")[1]);
							return vareNr;

							// If no, then get to choose a new product
						} else if (stringFromServer.split("\"")[1]
								.toLowerCase().equals("n")) {
							userConfirmed = true;

							Network.getInstance().getMettlerScaleCommands()
									.sendRM20("8", "Vare nr?", "x3");
							productInfo = "";
						}
					}
				}
			}
		}
		return id;
	}

	private double taraPhase() throws UnknownHostException,
			InterruptedException {
		String instruction = "Saet genstand der skal taras. y for at fortsaette";
		Network.getInstance().getMettlerScaleCommands()
				.sendRM20("8", instruction, "x3");

		boolean userStartedTara = false;
		boolean taraConfirmed = false;
		String taraValue = "";
		while (!userStartedTara) {
			Thread.sleep(100);
			stringFromServer = Network.getInstance().readFromServer();

			if (!stringFromServer.isEmpty()) {
				ui.writeToConsole(stringFromServer);
			}

			if (stringFromServer.equals("RM20 A \"Y\"")) {
				Network.getInstance().getMettlerScaleCommands().sendTara();
				while (!taraConfirmed) {
					Thread.sleep(100);

					stringFromServer = Network.getInstance().readFromServer();

					if (!stringFromServer.isEmpty()) {
						ui.writeToConsole(stringFromServer);
					}

					if (taraValue == "" && stringFromServer.contains("T S")) {
						taraValue = stringFromServer.substring(9,
								stringFromServer.length() - 3);
						Network.getInstance()
								.getMettlerScaleCommands()
								.sendRM20(
										"8",
										"Continue with the tara " + taraValue
												+ "? y/n", "x3");
					}

					if (stringFromServer.contains("RM20 A \"Y\"")
							&& !taraValue.isEmpty()) {
						return Double.parseDouble(taraValue);
					}

					if (stringFromServer.contains("RM20 A \"N\"")
							&& !taraValue.isEmpty()) {
						userStartedTara = false;
						taraConfirmed = false;
						break;
					}
				}
			}
		}
		return 0;
	}

	private double nettoPhase() throws UnknownHostException,
			InterruptedException {
		String instruction = "Paafyld vare og skriv y for at fortsætte";
		Network.getInstance().getMettlerScaleCommands()
				.sendRM20("8", instruction, "x3");

		boolean userStartedNetto = false;
		boolean nettoConfirmed = false;
		String nettoValue = "";
		while (!userStartedNetto) {
			Thread.sleep(100);
			stringFromServer = Network.getInstance().readFromServer();

			if (!stringFromServer.isEmpty()) {
				ui.writeToConsole(stringFromServer);
			}

			if (stringFromServer.equals("RM20 A \"Y\"")) {
				Network.getInstance().getMettlerScaleCommands().SendWeigh();
				while (!nettoConfirmed) {
					Thread.sleep(100);

					stringFromServer = Network.getInstance().readFromServer();

					if (!stringFromServer.isEmpty()) {
						ui.writeToConsole(stringFromServer);
					}

					if (nettoValue == "" && stringFromServer.contains("S S")) {
						nettoValue = stringFromServer.substring(9,
								stringFromServer.length() - 3);
						Network.getInstance()
								.getMettlerScaleCommands()
								.sendRM20(
										"8",
										"Fortsæt med netto " + nettoValue
												+ "? y/n", "x3");
					}

					if (stringFromServer.contains("RM20 A \"Y\"")
							&& !nettoValue.isEmpty()) {
						return Double.parseDouble(nettoValue);
					}

					if (stringFromServer.contains("RM20 A \"N\"")
							&& !nettoValue.isEmpty()) {
						userStartedNetto = false;
						nettoConfirmed = false;
						break;
					}
				}
			}
		}
		return 0;
	}

	private void bruttoControlPhase(double netto, double tara) throws UnknownHostException, InterruptedException{


		Network.getInstance()
				.getMettlerScaleCommands()
				.sendRM20("8",
						"Fjern vare og start brutto kontrol, skriv y for at fortsætte",
						"&3");

		boolean userStartedBC = false;
		boolean bCFinished = false;
		double weighedBrutto = netto + tara;
		double currentBrutto = 0;
		while (!userStartedBC) {
			Thread.sleep(100);

			stringFromServer = Network.getInstance().readFromServer();

			if (!stringFromServer.isEmpty()) {
				ui.writeToConsole(stringFromServer);
			}

			if (stringFromServer.contains("RM20 A \"Y\"")){
				double brutto = netto + tara;
				
				Network.getInstance().getMettlerScaleCommands().SendWeigh();
				while(!bCFinished) {
					
					stringFromServer = Network.getInstance().readFromServer();

					if (!stringFromServer.isEmpty()) {
						ui.writeToConsole(stringFromServer);
					}
					
					if (stringFromServer.contains("S S")) {
						currentBrutto = Double.parseDouble(stringFromServer.substring(9,
								stringFromServer.length() - 3));
						if ((Math.abs(currentBrutto - weighedBrutto)) > 0.010){
							Network.getInstance().getMettlerScaleCommands().sendWriteInDisplay("BC OK");
							userStartedBC = true;
							bCFinished = true;
						}
						else {
							Network.getInstance().getMettlerScaleCommands().sendWriteInDisplay("BC NOT OK");
							userStartedBC = true;
							bCFinished = true;
						}
					}
				}
			}
		}
	}

	public void logAndStorePhase() {
	db.updateStoreFile(vareNummer, netto);
	db.writeToLogFile(this.id, vareNummer, netto, netto);
	ui.writeToConsole("OPDATERET LAGER FIL");
	ui.writeToConsole("OPDATERET LOG FIL");
	}
}
